home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Hottest 6
/
Hottest 6 (1996)(PDSoft)[!].iso
/
software
/
rendering
/
pov
/
povray40
/
amiga.c
next >
Wrap
C/C++ Source or Header
|
1978-11-24
|
28KB
|
964 lines
/****************************************************************************
* amiga.c
*
* This module handles all of the Amiga-specific code for the raytracer.
*
* from Persistence of Vision Raytracer
* Copyright 1992 Persistence of Vision Team
*---------------------------------------------------------------------------
* Copying, distribution and legal info is in the file povlegal.doc which
* should be distributed with this file. If povlegal.doc is not available
* or for more info please contact:
*
* Drew Wells [POV-Team Leader]
* CIS: 73767,1244 Internet: 73767.1244@compuserve.com
* Phone: (213) 254-4041
*
* This program is based on the popular DKB raytracer version 2.12.
* DKBTrace was originally written by David K. Buck.
* DKBTrace Ver 2.0-2.12 were written by David K. Buck & Aaron A. Collins.
* HAM-8 Support by Markus Stipp
*
*****************************************************************************/
#include "frame.h"
#include "povproto.h"
#include <proto/exec.h>
#include <proto/intuition.h>
#include <proto/graphics.h>
#include <proto/dos.h>
#include <proto/expansion.h>
#include <exec/types.h>
#include <intuition/intuition.h>
#include <graphics/display.h>
#include <libraries/expansionbase.h>
void geta4(void);
void Requestor_Handler(void);
void Amiga_open(void);
void Amiga_close(void);
void open_requestor(void);
void close_requestor(void);
void write_byte(int x, int y, unsigned char n);
void write_hame_pixel(int x, int y, char Red, char Green, char Blue);
void write_cookie(unsigned char *brand, int line);
void make_hame_palette(struct ViewPort *vp);
void SetRGB8 (short reg, unsigned char rr, unsigned char gg,
unsigned char bb, short base);
void OpenFirecracker (void);
void write_firecracker_pixel(UWORD x, UWORD y, UBYTE r, UBYTE g, UBYTE b);
extern unsigned int Options;
extern char DisplayFormat;
extern FRAME Frame;
#define INT_REV 29L
#define GR_REV 29L
struct IntuitionBase *IntuitionBase;
struct GfxBase *GfxBase;
struct Screen *s;
volatile struct Window *w;
struct Task *Requestor_Task;
volatile int Requestor_Running;
volatile extern int Stop_Flag;
SHORT RegUsed = 2;
#define OFFSET 13
#define MINOFFSET 6
#define SCREEN_WIDTH 320
#define SCREEN_HEIGHT 512
#define HAM8_SCREEN_WIDTH 640
#define HAME_SCREEN_WIDTH 640
#define HAME_SCREEN_HEIGHT 402
struct NewScreen Ham_Screen =
{
0, 0,
SCREEN_WIDTH, SCREEN_HEIGHT,
6,
0, 1,
INTERLACE | HAM,
SCREENQUIET,
NULL,
(UBYTE *) "POV-Ray",
NULL,
NULL
};
struct NewScreen Ham8_Screen =
{
0, 0,
HAM8_SCREEN_WIDTH, SCREEN_HEIGHT,
8,
0, 1,
HIRES | INTERLACE | HAM,
SCREENQUIET,
NULL,
(UBYTE *) "POV-Ray",
NULL,
NULL
};
struct NewScreen Ham_E_Screen =
{
0, 0,
HAME_SCREEN_WIDTH, HAME_SCREEN_HEIGHT,
4,
0, 1,
INTERLACE | HIRES,
SCREENQUIET,
NULL,
(UBYTE *) "POV-Ray",
NULL,
NULL
};
int lacer; /* if non-zero, screen is an interlace screen. Set this... */
/* ...as soon as you open your HAM-E screen. */
unsigned char *fp0,*fp1,*fp2,*fp3; /* These are pointers which have been... */
/* ...cached from the screens BitMap[] */
/* ...array. This allows us to get at */
/* ...them much faster. Set them as soon */
/* ...as you open your HAM-E screen. */
unsigned char bitpat[] = /* This table is used as a table of masks... */
{ /* ...to isolate bits in the HAM-E pixels */
128,64,32,16,8,4,2,1,
};
unsigned char ham_cookie[] = /* ham mode cookie... preceeds any HAM... */
{ /* ...color registers, and triggers hardware */
0xA2,0xF5,0x84,0xDC, /* ...into ham mode. */
0x6D,0xB0,0x7F,0x18
};
struct Window *Requestor_Window;
volatile struct MsgPort *Requestor_Port;
struct IntuiText chip Body_Text =
{0, 1, JAM1, 5, 10, NULL, (UBYTE *) "Click to abort the picture", NULL};
struct IntuiText chip Abort_Text =
{0, 1, JAM1, 5, 3, NULL, (UBYTE *) "Abort", NULL};
UWORD chip ColorTbl[16] = { 0x000, 0x111, 0x222, 0x333, 0x444, 0x555, 0x666,
0x777, 0x888, 0x999, 0xaaa, 0xbbb, 0xccc, 0xddd,
0xeee, 0xfff };
LONG last_red = 0, last_green = 0, last_blue = 0, last_y = -1, last_x = -1;
/* Firecracker routines */
typedef struct BOARD {
ULONG orgb;
ULONG orgb2; /* autoincrementing */
UWORD pad;
UBYTE control0;
UBYTE control1;
UWORD y, x;
} BOARD;
BOARD *board;
int fc_width;
void amiga_init_POVRAY(void )
{
(void) onbreak(amiga_close_all);
}
int matherr (x)
struct __exception *x;
{
fprintf (stderr, "Math error type: %d from function %s values: %g %g\n",
x->type, x->name, x->arg1, x->arg2);
switch(x->type)
{
case DOMAIN:
case OVERFLOW:
x->retval = 1.0e17;
break;
case SING:
case UNDERFLOW:
x->retval = 0.0;
break;
case TLOSS:
case PLOSS:
return (0);
default:
break;
}
return(1);
}
void Requestor_Handler ()
{
Requestor_Port = CreatePort ("ray trace port", 0L);
Requestor_Window = BuildSysRequest
(NULL, &Body_Text, NULL, &Abort_Text, GADGETUP, 280L, 60L);
Wait ((1 << Requestor_Port -> mp_SigBit)
| (1 << Requestor_Window -> UserPort -> mp_SigBit));
Requestor_Running = FALSE;
Stop_Flag = TRUE;
}
void Amiga_open()
{
IntuitionBase = (struct IntuitionBase *) OpenLibrary ("intuition.library",INT_REV);
if (IntuitionBase == NULL)
exit(FALSE);
GfxBase = (struct GfxBase *) OpenLibrary ("graphics.library", GR_REV);
if (GfxBase == NULL)
exit(FALSE);
Requestor_Running = FALSE;
}
void Amiga_close()
{
if (Requestor_Running) {
Signal (Requestor_Task, 1 << Requestor_Port -> mp_SigBit);
Delay (2L);
}
if (Requestor_Window)
FreeSysRequest (Requestor_Window);
Requestor_Window = NULL;
CloseLibrary (GfxBase) ;
CloseLibrary (IntuitionBase) ;
}
void open_requestor()
{
Requestor_Window = NULL;
Stop_Flag = FALSE;
Requestor_Running = TRUE;
Requestor_Task = CreateTask ("Raytrace Requestor", 2L,
(APTR) Requestor_Handler, 20000L);
}
void display_finished ()
{
if (Requestor_Running) {
Signal (Requestor_Task, 1 << Requestor_Port -> mp_SigBit);
Delay (2L);
}
if (Requestor_Window)
FreeSysRequest (Requestor_Window);
Requestor_Window = NULL;
if (Options & PROMPTEXIT)
{
printf ("Finished.\nPress CR to quit.\n");
getchar();
}
}
void OpenFirecracker() {
struct ConfigDev *dev = NULL;
ULONG i;
ExpansionBase = (struct ExpansionBase *)
OpenLibrary("expansion.library", 0L);
if (!ExpansionBase) {
printf("No expansion library\n");
exit(999);
}
dev = FindConfigDev(NULL, 0x838, 0);
if (dev) {
board = (BOARD *)dev->cd_BoardAddr;
}
else {
printf("Can't find FireCracker\n");
exit(999);
}
CloseLibrary((struct Library *) ExpansionBase);
if (Frame.Screen_Width > 768) {
board->control0 = 0xf8;
fc_width = 1024;
}
else if (Frame.Screen_Width > 512) {
board->control0 = 0xb8;
fc_width = 768;
}
else if (Frame.Screen_Width > 384) {
board->control0 = 0x78;
fc_width = 512;
}
else {
board->control0 = 0x38;
fc_width = 384;
}
board->control1 = 0x7f;
board->y = 0; board->x = 0;
for (i=0; i<fc_width*482; i++) {
/* I write to the auto-increment and non-autoincrement registers
to make this work on 68000's as well as 68020's. */
board->orgb = 0x40404040;
board->orgb2 = 0x40404040;
}
}
void write_firecracker_pixel(x,y, r,g,b)
UWORD x,y;
UBYTE r,g,b;
{
ULONG v1,v2,v3,v;
int new_x, new_y;
v1 = r; v2 = g; v3 = b;
v = ((v1<<16)&0xff0000) + ((v2<<8)&0xff00) + (v3&0xff);
new_y = y+(482-Frame.Screen_Height)/2; new_x = x+(fc_width-Frame.Screen_Width)/2;
if ((new_x >= 0) && (new_y >= 0)
&& (new_x < fc_width) && (new_y < 482)) {
board->y = new_y;
board->x = new_x;
board->orgb2 = v;
}
}
/*:
.n write_byte()
.k low_level write_byte byte_write write_pixel
.b
SYNOPSIS: void write_byte(x,y,n);
short x;
int y;
unsigned char n;
FUNCTION: This function is similar to the Amiga's WritePixel routine.
is simply takes the incoming position and value and writes
them to the HAM-E screen appropriately.
INPUTS: x - horizontal position on screen.
y - vertical position on screen.
n - value 0-255 to write in the pixel.
RESULTS: None
BUGS: None Known.
LIMITATIONS:Hard coded for screen width of 320 pixels (640 hi-res pixels)
SEE ALSO: Global variables "fp3", "fp2", "fp1", "fp0", "bitpat[]"
:*/
void write_byte(x,y,n)
int x;
int y;
unsigned char n;
{
register int ypos,byte_offset;
register short bit_offset;
ypos = y * 80; /* index to correct scan line - note hard coded width! */
bit_offset = (x << 1) & 7; /* find base bit position */
byte_offset = (x >> 2); /* find base byte offset */
if (n & 128) *(fp3 + ypos + byte_offset) |= bitpat[bit_offset];
else *(fp3 + ypos + byte_offset) &= ~bitpat[bit_offset];
if (n & 64) *(fp2 + ypos + byte_offset) |= bitpat[bit_offset];
else *(fp2 + ypos + byte_offset) &= ~bitpat[bit_offset];
if (n & 32) *(fp1 + ypos + byte_offset) |= bitpat[bit_offset];
else *(fp1 + ypos + byte_offset) &= ~bitpat[bit_offset];
if (n & 16) *(fp0 + ypos + byte_offset) |= bitpat[bit_offset];
else *(fp0 + ypos + byte_offset) &= ~bitpat[bit_offset];
bit_offset++; /* to next nybble */
if (bit_offset == 8) /* carry into next byte? */
{
bit_offset=0;
byte_offset++;
}
if (n & 8) *(fp3 + ypos + byte_offset) |= bitpat[bit_offset];
else *(fp3 + ypos + byte_offset) &= ~bitpat[bit_offset];
if (n & 4) *(fp2 + ypos + byte_offset) |= bitpat[bit_offset];
else *(fp2 + ypos + byte_offset) &= ~bitpat[bit_offset];
if (n & 2) *(fp1 + ypos + byte_offset) |= bitpat[bit_offset];
else *(fp1 + ypos + byte_offset) &= ~bitpat[bit_offset];
if (n & 1) *(fp0 + ypos + byte_offset) |= bitpat[bit_offset];
else *(fp0 + ypos + byte_offset) &= ~bitpat[bit_offset];
}
/*:
.n write_cookie()
.k cookie low_level setup configure
.b
SYNOPSIS: void write_cookie(brand,line);
unsigned char *brand;
int line;
FUNCTION: This function writes the cookie on a particular line.
The variable "brand" is a pointer to an arrary of data
that contains the particular cookie for the mode you want.
These arrays are the global ones "ham_cookie[]" and
"reg_cookie[]".
Call as:
write_cookie(ham_cookie,line);
-or-
write_cookie(reg_cookie,line);
Note: If you have a four line palette, you need to call
this function for each successive line the palette exists
upon, for example:
write_cookie(reg_cookie,0);
write_cookie(reg_cookie,1);
write_cookie(reg_cookie,2);
write_cookie(reg_cookie,3);
-or-
for (i=0; i<4; i++)
{
write_cookie(reg_cookie,i);
}
If the global variable "lacer" is set, this function will
write the cookie data on the appropriate lines in both
fields... sending four lines of cookie to the function
with the lines 0,1,2,3 will write cookies on line pairs
0-1, 2-3, 4-5, and 6-7.
INPUTS: A pointer to the apropriate cookie and the line to put it on.
RESULTS: None
BUGS: None Known.
LIMITATIONS:None Known.
SEE ALSO: The global variable "lacer" and the "ham_cookie[]"
and reg_cookie[] global arrays.
:*/
void write_cookie(brand,line)
unsigned char *brand;
int line;
{
int i;
if (lacer) /* we need double the cookie data! */
{
for (i=0; i<8; i++)
{
write_byte(i,line*2,brand[i]);
write_byte(i,(line*2)+1,brand[i]);
}
}
else
{
for (i=0; i<8; i++)
{
write_byte(i,line,brand[i]);
}
}
}
/*:
.n make_hame_palette()
.k amiga_palette palette_amiga setup configure
.b
SYNOPSIS: void make_hame_palette(vp);
struct ViewPort *vp;
FUNCTION: Sets palette for Amiga side of hardware: The palette here is
designed to achieve two independant goals. First, and most
importantly, it creates a situation where the IRGB lines at
the Amiga's data port will exactly mirror the data in the
bitplanes of the screen as each pixel is emitted.
Secondly, this palette makes the images visible, if not
sensible, on a non HAM-e equipped Amiga... Hopefully this
distinctive color palette will quickly cue the user that
they are missing something good. :^)
IRGB to 12 bit correspondence:
bit 8 - b3 of red
bit 4 - b3 of green
bit 2 - b3 of blue
bit 1 - b0 of blue
INPUTS: A pointer to the ViewPort that "belongs" to this screen.
RESULTS: None
BUGS: None Known.
LIMITATIONS:None Known.
SEE ALSO:
:*/
void make_hame_palette(vp)
struct ViewPort *vp;
{
int rr,gg,bb,i;
int col;
col=0;
for (i=0; i<16; i++)
{
rr=0; gg=0; bb=0;
if (i & 8) rr = 8; /* this builds the IRGB bit outputs... */
if (i & 4) gg = 8; /* ...these four bits are all that are */
if (i & 2) bb = 8; /* ...required to make the HAM-E run, */
if (i & 1) bb |= 1; /* ...they xfer b0->b3 to the IRGB lines */
if (i != 0) /* we don't mess with c0 - we leave it black */
{
rr += (col & 7); /* build strange colors in cregs 1-15... */
col += 2; /* ...these extra bits sent to the color */
gg += (col & 7); /* ...registers make amiga palette very */
col += 2; /* ...interesting to look at if the HAM-E */
bb += (col & 6); /* ...is NOT attached. Otherwise useless. */
col += 2; /* ...The code in this "if" is optional. */
}
SetRGB4(vp,i,rr,gg,bb); /* this actually sets the Amiga color regs */
}
}
/*:
.n SetRGB8()
.k palette_hame hame_palette setup configure
.b
SYNOPSIS: void SetRGB8(reg,rr,gg,bb,base);
int reg,rr,gg,bb,base;
FUNCTION: This routine sets the color registers in the HAM-E hardware.
It can handle color registers located at any point on screen,
by setting the "base" variable to the starting scan line where
the color registers exist. Normally, the cookie and it's
associated color registers are located beginning at scan line 0.
If the screen is an interlace screen, this routine will set both
set of color registers identically; when in interlace, the
HAM-E maintains separate sets of color registers for the
odd and even interlace fields. Since this routine sets both
sets of color registers identically, you don't have to
worry about dealing with this feature.
INPUTS: reg - the color register number from 0 to 255 to be set
rr - the red value from 0-255
gg - the green value from 0-255
bb - the blue value from 0-255
base - the starting scan line of the first coookie position
(usually zero)
RESULTS: None
BUGS: None Known.
LIMITATIONS:None Known.
SEE ALSO: The global variable "lacer"
:*/
void SetRGB8(reg,rr,gg,bb,base)
short reg;
unsigned char rr,gg,bb;
short base;
{
short p_row,p_index;
p_row = (reg >> 6) + base; /* palette row 0-3. */
p_index = ((reg & 0x3f) * 3) + 8; /* reg 0-63 in p_row */
if (lacer) /* then we need both fields! */
{
/* for the even field: */
write_byte(p_index, p_row*2, rr); /* put RED value */
write_byte(p_index+1, p_row*2, gg); /* put GREEN value */
write_byte(p_index+2, p_row*2, bb); /* put BLUE value */
/* here is the stuff for the ODD field: */
write_byte(p_index, (p_row*2)+1, rr); /* put RED value */
write_byte(p_index+1, (p_row*2)+1, gg); /* put GREEN value */
write_byte(p_index+2, (p_row*2)+1, bb); /* put BLUE value */
}
else /* just write to one field */
{
write_byte(p_index, p_row, rr); /* put RED value */
write_byte(p_index+1, p_row, gg); /* put GREEN value */
write_byte(p_index+2, p_row, bb); /* put BLUE value */
}
}
void display_init (width, height)
int width, height;
{
Amiga_open();
open_requestor();
Delay (10);
if (DisplayFormat == 'E') {
if ((s = (struct Screen *) OpenScreen (&Ham_E_Screen)) == NULL)
exit (FALSE);
ShowTitle (s, FALSE);
lacer = 1;
fp0 = s->BitMap.Planes[0];
fp1 = s->BitMap.Planes[1];
fp2 = s->BitMap.Planes[2];
fp3 = s->BitMap.Planes[3];
make_hame_palette(&s->ViewPort);
SetAPen (&(s->RastPort), 0L);
RectFill (&(s -> RastPort), 0L, 0L, HAME_SCREEN_WIDTH-1, 1);
SetAPen (&(s->RastPort), 1L);
RectFill (&(s -> RastPort), 0L, 2L, HAME_SCREEN_WIDTH-1, HAME_SCREEN_HEIGHT-1);
write_cookie(ham_cookie, 0);
SetRGB8 (0x11, 0x80, 0x80, 0x80, 0);
}
else if (DisplayFormat == 'F') {
OpenFirecracker();
}
else if (DisplayFormat == '8') {
if ((s = (struct Screen *) OpenScreen (&Ham8_Screen)) == NULL)
exit (FALSE);
ShowTitle (s, FALSE);
SetRGB32(&(s->ViewPort), 0L, 0x00000000, 0x00000000, 0x00000000);
SetRGB32(&(s->ViewPort), 1L, 0x50000000, 0x50000000, 0x50000000);
SetAPen (&(s->RastPort), 1L);
RectFill (&(s->RastPort), 0L, 0L, 639L, 511L);
}
else {
if ((s = (struct Screen *) OpenScreen (&Ham_Screen)) == NULL)
exit (FALSE);
ShowTitle (s, FALSE);
LoadRGB4 (&(s->ViewPort), ColorTbl, 16L);
SetAPen (&(s->RastPort), 7L);
RectFill (&(s -> RastPort), 0L, 0L, 319L, 511L);
}
}
void display_close ()
{
if (Requestor_Running) {
Signal (Requestor_Task, 1 << Requestor_Port -> mp_SigBit);
Delay (2L);
}
if (Requestor_Window)
FreeSysRequest (Requestor_Window);
Requestor_Window = NULL;
if (DisplayFormat != 'F')
CloseScreen (s);
}
#define absdif(x,y) ((x > y) ? (x - y) : (y - x))
#define max3(x,y,z) ((x>y)?((x>z)?1:3):((y>z)?2:3))
void write_hame_pixel (x, y, Red, Green, Blue)
int x, y;
char Red, Green, Blue;
{
register unsigned char colour;
short delta_red, delta_green, delta_blue;
if ((x >= SCREEN_WIDTH ) || (y >= SCREEN_HEIGHT))
return;
Red = (Red >> 2) & 0x3F;
Green = (Green >> 2) & 0x3F;
Blue = (Blue >> 2) & 0x3F;
if (last_y != y) {
last_y = y;
last_red = last_green = last_blue = 0;
}
delta_red = absdif (Red, last_red);
delta_green = absdif (Green, last_green);
delta_blue = absdif (Blue, last_blue);
switch (max3(delta_red, delta_green, delta_blue)) {
case 1:
last_red = Red;
colour = 0x80 + Red;
break;
case 2:
last_green = Green;
colour = 0xc0 + Green;
break;
case 3:
last_blue = Blue;
colour = 0x40 + Blue;
break;
}
write_byte (x, y+2, colour);
}
void display_plot (x, y, Red, Green, Blue)
int x, y;
char Red, Green, Blue;
{
register short i;
short delta_red, delta_green, delta_blue;
register char MRed, MGreen, MBlue, RRed, RGreen, RBlue;
ULONG LRed, LGreen, LBlue, colour ;
BOOL RegFound = FALSE;
short RelError, RelError2;
ULONG Table[64][3];
if (DisplayFormat == 'E')
return (write_hame_pixel(x, y, Red, Green, Blue));
else if (DisplayFormat == 'F')
return (write_firecracker_pixel((UWORD) x, (UWORD) y, Red, Green, Blue));
else if (DisplayFormat == '8') {
if ((x >= s->Width ) || (y >= s->Height))
return;
LRed = (ULONG) Red;
LGreen = (ULONG) Green;
LBlue = (ULONG) Blue;
MRed = (Red >> 2) & 0x3F;
MGreen = (Green >> 2) & 0x3F;
MBlue = (Blue >> 2) & 0x3F;
if (x!=0) {
if (last_x +1 != x || last_y != y)
return;
}
if (last_y != y) {
last_y = y;
last_red = last_green = last_blue = 0;
}
last_x = x;
delta_red = absdif (MRed, last_red);
delta_green = absdif (MGreen, last_green);
delta_blue = absdif (MBlue, last_blue);
switch (max3(delta_red, delta_green, delta_blue)) {
case 1:
RelError = delta_green+delta_blue;
if(RelError > MINOFFSET)
{
GetRGB32(s->ViewPort.ColorMap, 0L, (ULONG) RegUsed, (ULONG *) &Table);
for (i=0; i<RegUsed; i++)
{
RRed = ((Table[i][0])>>2) & 0x3F;
RGreen = ((Table[i][1])>>2) & 0x3F;
RBlue = ((Table[i][2])>>2) & 0x3F;
RelError2 = absdif(RRed, MRed) + absdif(RGreen, MGreen) + absdif(RBlue, MBlue);
if(RelError2 < RelError)
{
RegFound = TRUE;
RelError = RelError2;
last_red = RRed;
last_green = RGreen;
last_blue = RBlue;
colour = (ULONG) i;
}
}
if(OFFSET < RelError)
{
if (RegUsed < 64)
{
LRed = LRed << 24;
LGreen = LGreen << 24;
LBlue = LBlue << 24;
SetRGB32(&(s->ViewPort), (ULONG) RegUsed, LRed, LGreen, LBlue);
colour = (ULONG) RegUsed++;
last_red = MRed;
last_green = MGreen;
last_blue = MBlue;
RegFound = TRUE;
}
}
}
if(!RegFound)
{
last_red = MRed;
colour = 0x80 + MRed;
}
break;
case 2:
RelError = delta_red+delta_blue;
if (RelError > MINOFFSET)
{
GetRGB32(s->ViewPort.ColorMap, 0L, (ULONG) RegUsed, (ULONG *) &Table);
for (i=0; i<RegUsed; i++)
{
RRed = ((Table[i][0])>>2) & 0x3F;
RGreen = ((Table[i][1])>>2) & 0x3F;
RBlue = ((Table[i][2])>>2) & 0x3F;
RelError2 = absdif(RRed, MRed) + absdif(RGreen, MGreen) + absdif(RBlue, MBlue);
if(RelError2 < RelError)
{
RegFound = TRUE;
RelError = RelError2;
last_red = RRed;
last_green = RGreen;
last_blue = RBlue;
colour = (ULONG) i;
}
}
if(OFFSET < RelError)
{
if (RegUsed < 64)
{
LRed = LRed << 24;
LGreen = LGreen << 24;
LBlue = LBlue << 24;
SetRGB32(&(s->ViewPort), (ULONG) RegUsed, LRed, LGreen, LBlue);
colour = (ULONG) RegUsed++;
last_red = MRed;
last_green = MGreen;
last_blue = MBlue;
RegFound = TRUE;
}
}
}
if(!RegFound)
{
last_green = MGreen;
colour = 0xC0 + MGreen;
}
break;
case 3:
RelError = delta_red+delta_green;
if(RelError > MINOFFSET)
{
GetRGB32(s->ViewPort.ColorMap, 0L, (ULONG) RegUsed, (ULONG *) &Table);
for (i=0; i<RegUsed; i++)
{
RRed = ((Table[i][0])>>2) & 0x3F;
RGreen = ((Table[i][1])>>2) & 0x3F;
RBlue = ((Table[i][2])>>2) & 0x3F;
RelError2 = absdif(RRed, MRed) + absdif(RGreen, MGreen) + absdif(RBlue, MBlue);
if(RelError2 < RelError)
{
RegFound = TRUE;
RelError = RelError2;
last_red = RRed;
last_green = RGreen;
last_blue = RBlue;
colour = (ULONG) i;
}
}
if(OFFSET < RelError)
{
if (RegUsed < 64)
{
LRed = LRed << 24;
LGreen = LGreen << 24;
LBlue = LBlue << 24;
SetRGB32(&(s->ViewPort), (ULONG) RegUsed, LRed, LGreen, LBlue);
colour = (ULONG) RegUsed++;
last_red = MRed;
last_green = MGreen;
last_blue = MBlue;
RegFound = TRUE;
}
}
}
if(!RegFound)
{
last_blue = MBlue;
colour = 0x40 + MBlue;
}
break;
}
SetAPen(&(s->RastPort), colour);
WritePixel(&(s->RastPort), x, y);
return;
}
/* HAM */
if ((x >= s->Width ) || (y >= s->Height))
return;
Red = (Red >> 4) & 0x0F;
Green = (Green >> 4) & 0x0F;
Blue = (Blue >> 4) & 0x0F;
if(x!=0)
{
if(last_x +1 != x || last_y != y)
return;
}
if (last_y != y) {
last_y = y;
last_red = last_green = last_blue = 0;
}
last_x = x;
delta_red = absdif (Red, last_red);
delta_green = absdif (Green, last_green);
delta_blue = absdif (Blue, last_blue);
switch (max3(delta_red, delta_green, delta_blue)) {
case 1:
last_red = Red;
colour = 0x20 + Red;
break;
case 2:
last_green = Green;
colour = 0x30 + Green;
break;
case 3:
last_blue = Blue;
colour = 0x10 + Blue;
break;
}
SetAPen(&(s->RastPort), colour);
WritePixel(&(s->RastPort), x, y);
}
int amiga_close_all ()
{
close_all();
return (1);
}